const Redwood = require('@redwood.dev/client').default
const fs = require('fs')

//
// Redwood setup
//
let node1Identity = Redwood.identity.random()
let node1Client = Redwood.createPeer({
    identity: node1Identity,
    httpHost: 'http://localhost:8080',
    rpcEndpoint: 'http://localhost:8081',
    onFoundPeersCallback: (peers) => {}
})

let node2Identity = Redwood.identity.random()
let node2Client = Redwood.createPeer({
    identity: node2Identity,
    httpHost: 'http://localhost:9090',
    rpcEndpoint: 'http://localhost:9091',
    onFoundPeersCallback: (peers) => {}
})

async function main() {
    await node1Client.authorize()
    await node2Client.authorize()
    await genesis()
    console.log('Done.')
    process.exit(0)
}

async function genesis() {
    await node1Client.rpc.subscribe({ stateURI: 'somegitprovider.org/gitdemo' })
    await node2Client.rpc.subscribe({ stateURI: 'somegitprovider.org/gitdemo' })

    // Upload the repo's files into the state tree.
    let indexHTML = fs.createReadStream('./repo/index.html')
    let scriptJS = fs.createReadStream('./repo/script.js')
    let readmeMD = fs.createReadStream('./repo/README.md')
    let redwoodJPG = fs.createReadStream('./repo/redwood.jpg')
    let { sha1: indexHTMLSha1, sha3: indexHTMLSha3 } = await node1Client.storeBlob(indexHTML)
    let { sha1: scriptJSSha1, sha3: scriptJSSha3 } = await node1Client.storeBlob(scriptJS)
    let { sha1: readmeMDSha1, sha3: readmeMDSha3 } = await node1Client.storeBlob(readmeMD)
    let { sha1: redwoodJPGSha1, sha3: redwoodJPGSha3 } = await node1Client.storeBlob(redwoodJPG)

    // Send the genesis tx to set up the repo (this is sort of like `git init`).
    //
    // The "somegitprovider.org/gitdemo" channel contains:
    //   - A link to the current worktree so that we can browse it like a regular website.
    //   - All of the commit data that Git expects.  The files are stored under a "files" key,
    //         and other important metadata are stored under the other keys.
    //   - A mapping of refs (usually, branches) to commit hashes.
    //   - A permissions validator that allows anyone to write to the repo but tries to keep
    //         people from writing to the wrong keys.
    let tx1 = {
        stateURI: 'somegitprovider.org/gitdemo',
        id: Redwood.utils.genesisTxID,
        parents: [],
        patches: [
            ' = ' + Redwood.utils.JSON.stringify({
                'demo': {
                    'Content-Type': 'link',
                    'value': 'state:somegitprovider.org/gitdemo/refs/heads/master/worktree'
                },
                'Merge-Type': {
                    'Content-Type': 'resolver/dumb',
                    'value': {}
                },
                'Validator': {
                    'Content-Type': 'validator/permissions',
                    'value': {
                        [node1Identity.address.toLowerCase()]: {
                            '^.*$': {
                                'write': true
                            }
                        },
                        '*': {
                            '^.*': {
                                'write': true
                            },
                        }
                    }
                },
                'refs': {
                    'heads': {}
                },
                'commits': {}
            }),
        ],
    }
    await node1Client.put(tx1)

    //
    // Now, let's simulate pushing the first commit.  This transaction looks exactly like the ones
    // generated by the Redwood git-remote-helper.
    //

    // Note: if you alter the contents of the ./repo subdirectory, you'll need to determine the
    // git commit hash of the first commit again, and then tweak these variables.  Otherwise,
    // you'll get a "bad object" error from git.
    let commit1Hash = '305c6e97a68ec38b4b89a4f1e5bc18c8ba2b76eb'
    let commit1Timestamp = '2022-01-10T19:44:38-06:00'

    let tx2 = {
        stateURI: 'somegitprovider.org/gitdemo',
        id: commit1Hash + '000000000000000000000000',
        parents: [ tx1.id ],
        patches: [
            `.commits.${commit1Hash} = ` + Redwood.utils.JSON.stringify({
                'message': 'First commit\n',
                'timestamp': commit1Timestamp,
                'author': {
                    'name': 'Bryn Bellomy',
                    'email': 'bryn@signals.io',
                    'timestamp': commit1Timestamp,
                },
                'committer': {
                    'name': 'Bryn Bellomy',
                    'email': 'bryn@signals.io',
                    'timestamp': commit1Timestamp,
                },
                'sig': '',
                'files': {
                    'README.md': {
                        'Content-Type': 'link',
                        'Content-Length': 104,
                        'mode': 33188,
                        'value': `blob:sha3:${readmeMDSha3}`,
                        'sha1': readmeMDSha1,
                    },
                    'redwood.jpg': {
                        'Content-Type': 'link',
                        'Content-Length': 1198230,
                        'mode': 33188,
                        'value': `blob:sha3:${redwoodJPGSha3}`,
                        'sha1': redwoodJPGSha1,
                    },
                    'index.html': {
                        'Content-Type': 'link',
                        'Content-Length': 8493,
                        'mode': 33188,
                        'value': `blob:sha3:${indexHTMLSha3}`,
                        'sha1': indexHTMLSha1,
                    },
                    'script.js': {
                        'Content-Type': 'link',
                        'Content-Length': 62,
                        'mode': 33188,
                        'value': `blob:sha3:${scriptJSSha3}`,
                        'sha1': scriptJSSha1,
                    }
                }
            }),
            `.refs.heads.master = ` + Redwood.utils.JSON.stringify({
                'HEAD': commit1Hash,
                'worktree': {
                    'Content-Type': 'link',
                    'value': `state:somegitprovider.org/gitdemo/commits/${commit1Hash}/files`
                }
            }),
        ],
    }
    await node1Client.put(tx2)
}

main()
